<?php
/* Licence:
 * =============================================================================
 * Copyright 2007  PANEL Martin
 * email : xxorax@gmail.com
 * website : http://www.xorax.info
 * 
 * This class is using for implement ajax field in wordpress.
 * 
 * This work is licensed under a Creative Commons Attribution-Share Alike 3.0
 * License (http://creativecommons.org/licenses/by-nd/3.0/)
 * You can alter or modify it but you must include this licence header.
 * If you write an other WordPress plugin with it and you alter or modify it,
 * you MUST change the name of the class (for not over-write class name when
 * WordPress loading).
*/

if (!function_exists("ob_get_clean")) {
  function ob_get_clean() {
    $ob_contents = ob_get_contents();
    ob_end_clean();
    return $ob_contents;
  }
}

if(!class_exists('xorax_wp_ajax_v1')){
class xorax_wp_ajax_v1 {
  var $fielddata;
  var $callclass;
  var $callclassname;
  var $plugin_page;
  
  /****** REGISTERING METHODS ******/
  function xorax_wp_ajax_v1 ($classname, $plugin_page){
    $this->callclassname = $classname;
    $this->plugin_page = basename($plugin_page);
    if(!class_exists($classname)){
      include_once(dirname($plugin_page).'/'.$classname.'.class.php');
      if(!class_exists($classname)) return;
    }
    $this->callclass = new $classname();
    add_action('admin_menu', array(&$this, 'admin_menu'));
    add_action('wp_ajax_'.$classname.'_xhr',array(&$this,'run'));
  }

  function admin_menu (){
    global $plugin_page;
    //print_r($GLOBALS);
    if (!function_exists('add_management_page')) return;
    $arg = array();
    if(is_callable(array(&$this->callclass, 'menu'))){
      $arg = call_user_func(array(&$this->callclass, 'menu'));
    }
    if(!is_array($arg)) $arg = array();
    if(!isset($arg[0])) $arg[0] = $this->callclassname.' Page';
    if(!isset($arg[1])) $arg[1] = $this->callclassname;
    if(!isset($arg[2])) $arg[2] = 8;
    $arg[3] = $this->plugin_page;
    $arg[4] = array(&$this,'run');
    call_user_func_array('add_management_page',$arg);
    
    if($plugin_page == $this->plugin_page){
      //wp_enqueue_script('xorax_wp_ajax','/wp-content/plugins/xorax_wp_ajax/xorax_wp_ajax.js',array('scriptaculous'));
      wp_enqueue_script('ajax_of_'.$this->callclassname,
        '/wp-content/plugins/readthis/xorax_wp_ajax/xorax_wp_ajax.js.php?class='.$this->callclassname,
        //array('scriptaculous')
        array('scriptaculous-builder','scriptaculous-effects')
      );
      wp_enqueue_script('dbx-admin-key', '/wp-admin/dbx-admin-key.js', array('dbx'));
      wp_localize_script('dbx-admin-key', 'dbxL10n', array(
          'manager' => $this->callclassname,
          'open' => __('open'),
          'close' => __('close'),
          'moveMouse' => __('click-down and drag to move this box'),
          'toggleMouse' => __('click to %toggle% this box'),
          'moveKey' => __('use the arrow keys to move this box'),
          'toggleKey' => __(', or press the enter key to %toggle% it'),
        ) );
      if(is_callable(array(&$this->callclass, 'head'))){
        //add_action('admin_head-'.$this->plugin_page, array($this->callclass, 'head')); //why wrong ??
        add_action('admin_head',array(&$this->callclass, 'head'));
      }
    }
  }
  /****** END OF REGISTERING METHODS ******/

  function run ($callclass){
    global $plugin_page;
    
    $this->fielddata = array();
    if(!isset($this->callclass->fields)) $this->callclass->fields = array();
    
    if(isset($_POST['action']) && $_POST['action'] == $this->callclassname.'_xhr'){
      //echo 'ok';
      if(!empty($_POST['field_action'])) {
        $this->screen_ajax($_POST['field_action']);
      }elseif(!empty($_POST['func_callback'])){
        $this->do_ajax_callback($_POST['func_callback']);
      }elseif(!empty($_POST['reload_field'])){
        $this->reload_field($_POST['reload_field']);
      }
    }elseif($this->plugin_page == $plugin_page){
      $this->screen($this->callclass->fields);
    }
  }
  
  function ajax_callback($func,$args){
    if(!is_array($args)) $args = array($args);
    return "xorax_wp_ajax_callback('$func','".base64_encode(serialize($args))."')";
  }
  
  function do_ajax_callback($f){
    $args = array();
    if(!empty($_POST['func_callback_args'])){
      $args = @unserialize(@base64_decode($_POST['func_callback_args']));
      if($args === false){
        $args = $_POST['func_callback_args'];
      }
    }
    $returned = $this->do_function($f, $args);
    
    $field = 'nofield';
    
    $fdata = array('field' => $field);
    if(!empty($returned['printed'])){
      $fdata['eval'] = 'Element.update("info","'.$returned['printed'].'");';
    }elseif(is_array($returned['returned'])){
      if(!empty($returned['returned']['field'])){
        $field = $returned['returned']['field'];
        $fdata = $returned['returned'];
      }
      //$returned['returned']
    } else {
      $fdata['eval'] = $returned['returned'];
    }

    $this->fielddata[$field] = $fdata;
    /*
    if($field != 'nofield'){
      $res = $this->do_function('field_'.$field);
      $this->fielddata[$field]['reload'] = $res['printed'];
    }
    */
    $this->display_xml();
  }
  
  function call_function($func, $args=array(), $global = true){
    $cb = array(&$this->callclass, $func);
    if(is_callable($cb) || ($global && is_callable($cb = $func))){
      return call_user_func_array($cb, $args);
    } else {
        echo 'error : not callable:'.$func;
        return false;
    }
  }
  
  function do_function($func, $args=array(), $global = true){
    ob_start();
    $response = $this->call_function($func, $args, $global);
    $print = ob_get_clean();
    return array(
      'returned' => $response,
      'printed' => $print
    );
  }
  
  function reload_field($field){
    $res = $this->do_function('field_'.$field);
    $this->fielddata[$field]['reload'] = $res['printed'];
    $this->fielddata[$field]['field'] = $field;
    $this->display_xml();
  }    
  
  function action ($field_id){
    $response = array();
    if(!empty($_POST['field_action']) && $_POST['field_action'] == $field_id){
      $returned = $this->do_function('field_'.$field_id.'_action');
      if(!is_array($returned['returned'])){
        $response = array('head'=> $returned['returned']);
      } else {
        $response = $returned['returned'];
      }
      if(!empty($returned['printed'])) $response['foot'] = $returned['printed'];
    }
    $response['field'] = $field_id;
    
    return $this->fielddata[$field_id] = $response;
  }
  
  function screen_ajax(){ $fields = func_get_args();
    if(is_array($fields[0])) $fields = $fields[0];
    
    for($i=0;$i<count($fields); $i++){
      $field = $fields[$i];
      $this->action($field);
      if(!empty($this->fielddata[$field]['reload'])){
        $r = $this->do_function('field_'.$field);
        $this->fielddata[$field]['reload'] = $r['printed'];
      }
    }
    $this->display_xml();
  }
  
  function display_xml(){
    if(!$this->fielddata) exit();
    header('Content-type: text/xml; charset=' . get_option('blog_charset'), true);
    echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'."\n";
    ?><root>
      <?php foreach($this->fielddata as $v): ?>
      <item>
        <field><?php echo $v['field']; ?></field>
        <?php foreach(array('head','foot','reload','eval') as $p){
          if(!empty($v[$p])) echo '<'.$p.'><![CDATA['.$v[$p].']]></'.$p.">\n";
        } /*?>
        if($v['head']): ?><head><![CDATA[<?php echo $v['head']; ?>]]></head><?php endif;
        if($v['foot']): ?><foot><![CDATA[<?php echo $v['foot']; ?>]]></foot><?php endif;
        if($v['reload']): ?><reload><![CDATA[<?php echo $v['reload']; ?>]]></reload><?php endif;
        if($v['eval']): ?><eval><![CDATA[<?php echo $v['eval']; ?>]]></eval><?php endif; */?>
      </item>
    <?php endforeach; ?></root><?php
    die();
  }
  
  function screen ($fields){
    if(!is_array($fields)) return false;
    ?>
    <div id='info'></div>
    <div class=wrap id="xorax_wp_ajax_content">
      <h2><?php $this->callclass->title(); ?></h2>
      <div id="advancedstuff" class="dbx-group">
      <?php
      foreach($fields as $field){
        $this->action($field);
        
        $r = $this->do_function('field_'.$field);
        $content = &$r['printed'];
        if(empty($content)) continue; //no display field if content is empty
        $title = 'notitle';
        $id = $field;
        $writeform = true;
        if(is_array($r['returned'])){
          if(isset($r['returned']['title'])) $title = $r['returned']['title'];
          if(isset($r['returned']['id'])) $id = $r['returned']['id'];
          if(isset($r['returned']['writeform'])) $writeform = ($r['returned']['writeform'] == true);
        }
        $this->field($title, $content, $id, $writeform);
      } ?>
    </div></div><?php
    
    if($this->err){
      echo implode('<br/>',$this->err);
    }
  }
  
  function field ($title, &$content, $id = '', $writeform = true) {
    ?><div class="dbx-b-ox-wrapper">
      <div <?php if(!empty($id)) echo 'id="'.$id.'" '; ?>class="dbx-box" style="width:100%">
        <div class="dbx-h-andle-wrapper">
          <h3 class="dbx-handle"><?php echo $title ?>
          <span style="float:right"><a href="#" onclick="xorax_wp_ajax_reload_field('<?php echo $id; ?>'); return false;">reload</a></span></h3>
        </div>
        <div class="dbx-c-ontent-wrapper">
    <?php if($writeform){ ?>
    <form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; if(!empty($id)) echo '#'.$id; ?>">
    <input type="hidden" name="field_action" value="<?php echo $id; ?>" />
    <?php } ?>
          <div class="dbx-content">
            <div id="<?php echo $id.'--head'; ?>"><?php echo $this->fielddata[$id]['head']; ?></div>
            <div id="<?php echo $id.'--content'; ?>"><?php echo $content; ?></div>
            <div id="<?php echo $id.'--foot'; ?>"><?php echo $this->fielddata[$id]['foot']; ?></div>
          </div>
    </form>
        </div>
      </div>
    </div>
    <?php
  }
}
}
?>